"""
对话API路由
支持HTTP和WebSocket两种方式
"""
from typing import Optional
from fastapi import APIRouter, WebSocket, WebSocketDisconnect, Depends, HTTPException, status, Request
from fastapi.responses import StreamingResponse
from pydantic import BaseModel, Field
from sqlalchemy.ext.asyncio import AsyncSession
from loguru import logger

from app.core.deps import get_db, get_current_user
from app.core.agent import customer_service_agent
from app.models.user import User
from app.db.redis_client import redis_manager
import uuid


router = APIRouter()


# ==================== Pydantic模型 ====================

class ChatRequest(BaseModel):
    """聊天请求"""
    message: str = Field(..., description="用户消息", min_length=1, max_length=2000)
    use_rag: bool = Field(True, description="是否使用RAG检索")
    stream: bool = Field(False, description="是否流式响应")


class ChatResponse(BaseModel):
    """聊天响应"""
    success: bool = Field(..., description="是否成功")
    reply: str = Field(..., description="AI回复")
    used_rag: bool = Field(False, description="是否使用了RAG")
    retrieved_docs: list = Field(default_factory=list, description="检索到的文档")
    tokens: Optional[dict] = Field(None, description="Token使用情况")
    cost: Optional[float] = Field(None, description="调用成本")
    duration: Optional[float] = Field(None, description="响应时间")


class ConversationHistoryResponse(BaseModel):
    """对话历史响应"""
    success: bool
    history: list
    total: int


# ==================== HTTP API ====================

@router.post("/chat", response_model=ChatResponse)
async def chat(
    chat_request: ChatRequest,
    http_request: Request,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db)
):
    """
    对话接口（非流式）- 需要登录
    
    发送消息给AI客服，获取回复
    """
    try:
        # 使用用户ID作为会话标识
        user_id = str(current_user.id)
        
        logger.info(f"收到对话请求 | 用户: {user_id} | 消息长度: {len(chat_request.message)}")
        
        # 调用Agent处理
        result = await customer_service_agent.chat(
            user_id=user_id,
            message=chat_request.message,
            use_rag=chat_request.use_rag,
            save_history=True
        )
        
        if not result.get("success"):
            raise HTTPException(
                status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
                detail=result.get("error", "处理失败")
            )
        
        response = ChatResponse(
            success=True,
            reply=result["reply"],
            used_rag=result.get("used_rag", False),
            retrieved_docs=result.get("retrieved_docs", []),
            tokens=result.get("tokens"),
            cost=result.get("cost"),
            duration=result.get("duration"),
        )
        
        # 在响应头中返回会话ID（用于前端保存）
        from fastapi import Response as FastAPIResponse
        
        return response
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"对话处理失败: {e}", exc_info=True)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"系统错误: {str(e)}"
        )


@router.post("/chat/stream")
async def chat_stream(
    chat_request: ChatRequest,
    http_request: Request,
    current_user: User = Depends(get_current_user)
):
    """
    对话接口（流式）- 需要登录
    
    使用Server-Sent Events流式返回AI回复
    """
    try:
        # 使用用户ID作为会话标识
        user_id = str(current_user.id)
        
        logger.info(f"收到流式对话请求 | 用户: {user_id}")
        
        async def generate():
            """生成器函数，逐字返回AI回复"""
            try:
                async for chunk in customer_service_agent.chat_stream(
                    user_id=user_id,
                    message=chat_request.message,
                    use_rag=chat_request.use_rag,
                    save_history=True
                ):
                    # 使用SSE格式
                    yield f"data: {chunk}\n\n"
                
                # 发送结束标记
                yield "data: [DONE]\n\n"
                
            except Exception as e:
                logger.error(f"流式生成失败: {e}")
                yield f"data: [ERROR] {str(e)}\n\n"
        
        return StreamingResponse(
            generate(),
            media_type="text/event-stream",
            headers={
                "Cache-Control": "no-cache",
                "Connection": "keep-alive",
                "X-Accel-Buffering": "no",  # 禁用Nginx缓冲
            }
        )
        
    except Exception as e:
        logger.error(f"流式对话处理失败: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"系统错误: {str(e)}"
        )


@router.get("/greeting")
async def get_greeting():
    """
    获取欢迎语
    """
    try:
        greeting = await customer_service_agent.get_greeting()
        return {
            "success": True,
            "greeting": greeting
        }
    except Exception as e:
        logger.error(f"获取欢迎语失败: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"系统错误: {str(e)}"
        )


@router.get("/history", response_model=ConversationHistoryResponse)
async def get_conversation_history(
    limit: int = 20,
    current_user: User = Depends(get_current_user)
):
    """
    获取对话历史
    """
    try:
        user_id = str(current_user.id)
        
        history = await redis_manager.get_conversation_history(
            user_id=user_id,
            limit=limit
        )
        
        return ConversationHistoryResponse(
            success=True,
            history=history,
            total=len(history)
        )
        
    except Exception as e:
        logger.error(f"获取对话历史失败: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"系统错误: {str(e)}"
        )


@router.delete("/history")
async def clear_conversation_history(
    current_user: User = Depends(get_current_user)
):
    """
    清除对话历史
    """
    try:
        user_id = str(current_user.id)
        
        success = await customer_service_agent.clear_conversation(user_id)
        
        return {
            "success": success,
            "message": "对话历史已清除" if success else "清除失败"
        }
        
    except Exception as e:
        logger.error(f"清除对话历史失败: {e}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"系统错误: {str(e)}"
        )


# ==================== WebSocket API ====================

class ConnectionManager:
    """WebSocket连接管理器"""
    
    def __init__(self):
        # 存储活跃连接：{user_id: websocket}
        self.active_connections: dict[str, WebSocket] = {}
    
    async def connect(self, user_id: str, websocket: WebSocket):
        """连接"""
        await websocket.accept()
        self.active_connections[user_id] = websocket
        logger.info(f"WebSocket连接建立 | 用户: {user_id} | 活跃连接数: {len(self.active_connections)}")
    
    def disconnect(self, user_id: str):
        """断开连接"""
        if user_id in self.active_connections:
            del self.active_connections[user_id]
            logger.info(f"WebSocket连接断开 | 用户: {user_id} | 活跃连接数: {len(self.active_connections)}")
    
    async def send_message(self, user_id: str, message: dict):
        """发送消息"""
        websocket = self.active_connections.get(user_id)
        if websocket:
            await websocket.send_json(message)
    
    async def broadcast(self, message: dict):
        """广播消息"""
        for user_id, websocket in self.active_connections.items():
            try:
                await websocket.send_json(message)
            except Exception as e:
                logger.error(f"广播消息失败 | 用户: {user_id} | 错误: {e}")


# 全局连接管理器
manager = ConnectionManager()


@router.websocket("/ws")
async def websocket_endpoint(
    websocket: WebSocket,
    token: Optional[str] = None
):
    """
    WebSocket连接端点
    
    客户端应该通过token参数传递JWT令牌进行认证
    """
    user_id = None
    
    try:
        # TODO: 验证token，获取user_id
        # 暂时使用简单的处理
        if not token:
            await websocket.close(code=1008, reason="缺少认证令牌")
            return
        
        # 简化处理：直接使用token作为user_id（实际应该解析JWT）
        user_id = token
        
        # 建立连接
        await manager.connect(user_id, websocket)
        
        # 发送欢迎消息
        greeting = await customer_service_agent.get_greeting()
        await manager.send_message(user_id, {
            "type": "greeting",
            "content": greeting,
            "timestamp": None
        })
        
        # 接收和处理消息
        while True:
            # 接收客户端消息
            data = await websocket.receive_json()
            message_type = data.get("type", "chat")
            
            if message_type == "chat":
                # 处理对话消息
                user_message = data.get("message", "")
                use_rag = data.get("use_rag", True)
                
                if not user_message:
                    await manager.send_message(user_id, {
                        "type": "error",
                        "content": "消息不能为空"
                    })
                    continue
                
                # 发送"正在输入"状态
                await manager.send_message(user_id, {
                    "type": "typing",
                    "content": "AI正在思考中..."
                })
                
                # 流式响应
                full_reply = ""
                async for chunk in customer_service_agent.chat_stream(
                    user_id=user_id,
                    message=user_message,
                    use_rag=use_rag,
                    save_history=True
                ):
                    full_reply += chunk
                    await manager.send_message(user_id, {
                        "type": "chunk",
                        "content": chunk
                    })
                
                # 发送完成标记
                await manager.send_message(user_id, {
                    "type": "done",
                    "content": full_reply
                })
            
            elif message_type == "ping":
                # 心跳检测
                await manager.send_message(user_id, {
                    "type": "pong"
                })
            
            elif message_type == "clear":
                # 清除历史
                await customer_service_agent.clear_conversation(user_id)
                await manager.send_message(user_id, {
                    "type": "cleared",
                    "content": "对话历史已清除"
                })
            
            else:
                await manager.send_message(user_id, {
                    "type": "error",
                    "content": f"未知的消息类型: {message_type}"
                })
    
    except WebSocketDisconnect:
        logger.info(f"WebSocket客户端主动断开 | 用户: {user_id}")
    except Exception as e:
        logger.error(f"WebSocket错误: {e}", exc_info=True)
    finally:
        if user_id:
            manager.disconnect(user_id)

